package edu.uj.petri.model;

/**
 * implementation of Matrix using Jama library
 * @author Piotrek
 */
public class JamaMatrix extends Matrix {
    private Jama.Matrix matrixImpl;

    public JamaMatrix(int rows, int cols) {
        matrixImpl = new Jama.Matrix(rows, cols);
    }

    public double get(int i, int j) {
        return matrixImpl.get(i,j);
    }

    public void set(int i, int j, double val) {
        matrixImpl.set(i, j, val);
    }

    public int getRowCount() {
        return matrixImpl.getRowDimension();
    }

    public int getColumnCount() {
        return matrixImpl.getColumnDimension();
    }
    
     public static Matrix identity(int i,int j){

        Jama.Matrix ret = Jama.Matrix.identity(i,j);
        JamaMatrix jmRet = new JamaMatrix(i,j);
        
        for(int ii = 0;ii < i; ++ii){
            for(int jj = 0;jj < j;++jj){
                double val = ret.get(ii,jj);
                jmRet.set(ii,jj,val);
            }
        }
         return jmRet;
                 
    }
     
   public Matrix multiply(Matrix B){

        int r = B.getRowCount();
        int c = B.getColumnCount();
        Jama.Matrix jm = toJama(B);
        Jama.Matrix ret = new Jama.Matrix(r,c);
        
        ret = this.matrixImpl.times(jm);
        
        JamaMatrix jmRet = new JamaMatrix(r,c);
        
        for(int ii = 0;ii < r; ++ii){
            for(int jj = 0;jj < c;++jj){
                double val = ret.get(ii,jj);
                jmRet.set(ii,jj,val);
            }
        }
        
        return jmRet;
    }     
     
     
   private Jama.Matrix toJama(Matrix B){

        int r = B.getRowCount();
        int c = B.getColumnCount();
        Jama.Matrix jm = new Jama.Matrix(r,c);
        
        for(int ii = 0;ii < r; ++ii){
            for(int jj = 0;jj < c;++jj){
                double val = B.get(ii,jj);
                jm.set(ii,jj,val);
            }
        }
        
        
        return jm;
    }     
     
    public Matrix transpose(){
        
        Jama.Matrix jm = toJama(this);
        Jama.Matrix ret =  jm.transpose();
        
        int r = ret.getRowDimension();
        int c = ret.getColumnDimension();
        
        JamaMatrix jmRet = new JamaMatrix(r,c);
        
        for(int ii = 0;ii < r; ++ii){
            for(int jj = 0;jj < c;++jj){
                double val = ret.get(ii,jj);
                jmRet.set(ii,jj,val);
            }
        }
        return jmRet;
    }
    
    public double[] getRow(int r) {
        double[][] t = this.matrixImpl.getArray();
        return t[r];
    }
    
    public void setRow(int r, double row[]) {
        for( int ii = 0; ii < this.getColumnCount(); ++ii){
            double val = row[ii];
            this.matrixImpl.set(r,ii,val);
        }
    }
    
    public double[] getRowCopy(int r) {
        double row[] = new double[this.getColumnCount()];
        for(int ii = 0; ii < this.getColumnCount();++ii )
            row[ii] = this.matrixImpl.get(r,ii);
        return row;
    }
    
    public Matrix eliminateRow(int row) {
        int m = getRowCount(), n = this.getColumnCount();
        int[] rows = new int [m-1]; // array of cols which will not be eliminated
        int count = 0;
        
        for (int i = 0; i < m; i++) {
            if (i != row)
                rows[count++] = i;
        }
        
        Matrix reduced = getMatrix(rows, 0, n-1);
        return reduced;
    }
/** Gets a submatrix */    
    public Matrix getMatrix(int i0, int i1, int j0, int j1) {
        Matrix X = new JamaMatrix(i1-i0+1,j1-j0+1);
        //int[][] B = X.getArray();
        try {
            for (int i = i0; i <= i1; i++) {
                for (int j = j0; j <= j1; j++) {
                    double val = this.get(i,j);
                    X.set(i-i0,j-j0,val);
                }
            }
        } catch(ArrayIndexOutOfBoundsException e) {
            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
        }
        return X;
    }
/** Gets a submatrix */    
   
    public Matrix getMatrix(int[] r, int j0, int j1) {
        Matrix X = new JamaMatrix(r.length,j1-j0+1);
        //int[][] B = X.getArray();
        try {
            for (int i = 0; i < r.length; i++) {
                for (int j = j0; j <= j1; j++) {
                    double val = this.get(r[i],j);
                    X.set(i,j-j0,val);
                }
            }
        } catch(ArrayIndexOutOfBoundsException e) {
            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
        }
        return X;
    }
    
    public static Matrix copy(Matrix m){
        int i = m.getRowCount();
        int j = m.getColumnCount();
        JamaMatrix jmRet = new JamaMatrix(i,j);
        
        for(int ii = 0;ii < i; ++ii){
            for(int jj = 0;jj < j;++jj){
                double val = m.get(ii,jj);
                jmRet.set(ii,jj,val);
            }
        }
         return jmRet;           
           
    }
    


}
